package com.hmx.openplatform.gateway.filters;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.hmx.openplatform.commons.constans.BaseResultBean;
import com.hmx.openplatform.commons.constans.ExceptionDict;
import com.hmx.openplatform.commons.constans.SystemParams;
import com.hmx.openplatform.gateway.feign.CacheService;
import com.hmx.openplatform.gateway.utils.Md5Util;
import com.netflix.zuul.ZuulFilter;
import com.netflix.zuul.context.RequestContext;
import com.netflix.zuul.exception.ZuulException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.netflix.zuul.filters.support.FilterConstants;
import org.springframework.stereotype.Component;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.Enumeration;
import java.util.HashMap;

/**
 * Description:
 * 当前的过滤器主要作用是用于校验用户的请求中的签名是否正确，来判断是否是合法的请求
 * @author hmx
 * @date Created on 2021/5/24
 */
@Component

public class SignFilter extends ZuulFilter {

    @Autowired
    private CacheService cacheService;
    @Autowired
    private ObjectMapper objectMapper;
    
    @Override
    public String filterType() {
        return FilterConstants.PRE_TYPE;
    }

    @Override
    public int filterOrder() {
        return 30;
    }

    @Override
    public boolean shouldFilter() {
        return RequestContext.getCurrentContext().sendZuulResponse();
    }

    @Override
    public Object run() throws ZuulException {
        /**
         * 首先回顾下我们规则，我们的规则是将用户传递的参数中除了签名之外的数据，按照key的字典顺序进行排序，然后将排序后数据按照keyvaluekeyvalue的方式
         * 然后再获取用户的签名的秘钥，进行拼接，得到一个新的字符串，然后计算md5值，将计算的结果和用户传递的数据进行比较，一致则放行
         * 我们需要的数据就是用户传递的参数，用户的app的秘钥，用户传递的签名
         */
        RequestContext currentContext = RequestContext.getCurrentContext();
        HttpServletRequest request = currentContext.getRequest();
        Enumeration<String> parameterNames = request.getParameterNames();
        HashMap<String, String> signMap = new HashMap<>();
        while(parameterNames.hasMoreElements()){
            String name = parameterNames.nextElement();//获取每一个参数的名字
            if(!"sign".equalsIgnoreCase(name)){
                signMap.put(name,request.getParameter(name));//保存处sign之外的数据
            }
        }
        //我们现在要获取appsecret
        String app_key = request.getParameter("app_key");//获取应用的app key
        try{
            String appSecret = cacheService.hGet(SystemParams.APPKEY_REDIS_PRE + app_key, "appSecret");
            String md5Signature = Md5Util.md5Signature(signMap, appSecret);
            String sign = request.getParameter("sign");
            if(md5Signature.equals(sign)){
                return null;//校验通过
            }
            System.out.println("系统计算的签名: " + md5Signature);
            System.out.println("用户传递的签名: " + sign);
        } catch (Exception e) {
            e.printStackTrace();
        }
        //不管发生什么情况导致的校验失败，最终都会来这里执行代码
        currentContext.setSendZuulResponse(false);
        HttpServletResponse response = currentContext.getResponse();
        response.setContentType("application/json;charset=utf-8");
        BaseResultBean bean = new BaseResultBean();
        bean.setCode(ExceptionDict.SYSTEMPARAM_SIGN_ERROR);
        bean.setMsg("签名校验失败");

        try {
            currentContext.setResponseBody(objectMapper.writeValueAsString(bean));
        } catch (JsonProcessingException e) {
            e.printStackTrace();
        }
        return null;
    }
}
